package com.symaster.backups.util;

import java.awt.event.ActionListener;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author yinmiao
 * @version 2023/12/15
 */
public class DeferUpdate implements Runnable {

    private long deferTime = 1000;

    private long startTime;
    private ActionListener actionListener;
    private final Object treeLock = new Object();
    private boolean defer = false;

    private final ThreadPoolExecutor commonThreadPool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1));
    private boolean close;

    public DeferUpdate() {
        close = false;
        commonThreadPool.execute(this);
    }

    public void stop() {
        synchronized (treeLock) {
            defer = false;
        }
    }

    public int deferUpdate(ActionListener actionListener, long deferTime) {
        synchronized (treeLock) {
            this.deferTime = deferTime;
            this.actionListener = actionListener;
            this.startTime = System.currentTimeMillis();

            int ret;
            if (defer) {
                ret = 1;
            } else {
                ret = 0;
            }
            if (!defer) {
                defer = true;
            }
            return ret;
        }
    }

    @Override
    public void run() {

        try {
            while (!close) {
                TimeUnit.MILLISECONDS.sleep(10);
                synchronized (treeLock) {
                    if (defer) {
                        if (System.currentTimeMillis() - startTime > deferTime) {
                            if (actionListener != null) {
                                try {
                                    actionListener.actionPerformed(null);
                                } catch (Exception e) {
                                    e.printStackTrace(System.err);
                                }
                            }
                            defer = false;
                        }
                    }
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void close() {
        close = true;
        commonThreadPool.shutdown();
    }
}
